package com.djf.djfpgsql.wrapper.comparison;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.djf.djfpgsql.entity.User;
import com.djf.djfpgsql.wrapper.mapper.UserWrapperMapper;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 纯Wrapper方法对比示例
 * 展示不使用apply()拼接SQL的纯Wrapper方式与传统方式的区别
 */
@Service
public class WrapperComparisonService extends ServiceImpl<UserWrapperMapper, User> {

    // ==================== 纯Wrapper方式（推荐） ====================
    
    /**
     * 纯Wrapper方式：条件查询
     * 特点：
     * 1. 不拼接SQL字符串
     * 2. 类型安全，编译时检查
     * 3. 自动处理参数绑定
     * 4. MySQL和PostgreSQL完全兼容
     */
    public List<User> getUsersByConditionsPureWrapper(String name, Integer minAge, Boolean isActive) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        // 不拼接SQL，直接使用方法
        if (name != null && !name.isEmpty()) {
            wrapper.like("name", name);  // 自动生成: name LIKE '%value%'
        }
        
        if (minAge != null) {
            wrapper.ge("age", minAge);   // 自动生成: age >= ?
        }
        
        if (isActive != null) {
            wrapper.eq("is_active", isActive);  // 自动处理布尔值转换
        }
        
        wrapper.orderByDesc("created_at");  // 自动生成: ORDER BY created_at DESC
        
        return list(wrapper);
    }
    
    /**
     * 纯Wrapper方式：复杂条件组合
     * 特点：
     * 1. 链式调用，逻辑清晰
     * 2. 支持and/or逻辑组合
     * 3. 自动处理括号和优先级
     */
    public List<User> getComplexConditionsPureWrapper(String keyword, Integer minAge, Double minBalance) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        // 复杂条件组合，不需要手写SQL
        wrapper.and(w -> w
            .like("name", keyword)      // name LIKE '%keyword%'
            .or()
            .like("email", keyword)     // OR email LIKE '%keyword%'
        )
        .ge("age", minAge)              // AND age >= minAge
        .ge("balance", minBalance)      // AND balance >= minBalance
        .orderByDesc("balance", "created_at");  // ORDER BY balance DESC, created_at DESC
        
        return list(wrapper);
    }
    
    /**
     * 纯Wrapper方式：动态条件构建
     * 特点：
     * 1. 条件可选，自动忽略null值
     * 2. 不需要复杂的if-else判断
     * 3. 代码简洁，易于维护
     */
    public List<User> getDynamicConditionsPureWrapper(
            String name, String email, Integer minAge, Integer maxAge, 
            Double minBalance, Boolean isActive, LocalDateTime startDate) {
        
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        // 使用条件表达式，自动处理null值
        wrapper.like(name != null && !name.isEmpty(), "name", name)
               .like(email != null && !email.isEmpty(), "email", email)
               .ge(minAge != null, "age", minAge)
               .le(maxAge != null, "age", maxAge)
               .ge(minBalance != null, "balance", minBalance)
               .eq(isActive != null, "is_active", isActive)
               .ge(startDate != null, "created_at", startDate)
               .orderByDesc("created_at");
        
        return list(wrapper);
    }
    
    /**
     * 纯Wrapper方式：批量更新
     * 特点：
     * 1. 类型安全的字段设置
     * 2. 自动处理时间格式
     * 3. 支持条件更新
     */
    public boolean batchUpdatePureWrapper(List<Long> userIds, Boolean newStatus) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        
        // 不拼接SQL，使用方法设置
        wrapper.in("id", userIds)                           // WHERE id IN (...)
               .set("is_active", newStatus)                 // SET is_active = ?
               .set("updated_at", LocalDateTime.now());     // SET updated_at = ?
        
        return update(wrapper);
    }
    
    /**
     * 纯Wrapper方式：分页查询
     * 特点：
     * 1. 结合分页插件使用
     * 2. 自动处理LIMIT和OFFSET
     * 3. 支持排序
     */
    public List<User> getPagedUsersPureWrapper(int page, int size, String sortField, boolean isAsc) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        // 动态排序，不拼接SQL
        if (isAsc) {
            wrapper.orderByAsc(sortField);
        } else {
            wrapper.orderByDesc(sortField);
        }
        
        // 使用LIMIT语法（MySQL和PostgreSQL通用）
        int offset = (page - 1) * size;
        wrapper.last("LIMIT " + size + " OFFSET " + offset);
        
        return list(wrapper);
    }

    // ==================== 对比：传统方式的问题 ====================
    
    /**
     * 传统方式示例（不推荐）
     * 问题：
     * 1. 字符串拼接，容易出错
     * 2. 没有类型检查
     * 3. SQL注入风险
     * 4. 难以维护
     */
    public List<User> getUsersByConditionsTraditional(String name, Integer minAge, Boolean isActive) {
        // 这种方式存在很多问题
        StringBuilder sql = new StringBuilder("SELECT * FROM users WHERE 1=1");
        
        if (name != null && !name.isEmpty()) {
            sql.append(" AND name LIKE '%").append(name).append("%'");  // SQL注入风险！
        }
        
        if (minAge != null) {
            sql.append(" AND age >= ").append(minAge);
        }
        
        if (isActive != null) {
            // 需要手动处理布尔值转换
            sql.append(" AND is_active = ").append(isActive ? 1 : 0);  // 假设MySQL
        }
        
        sql.append(" ORDER BY created_at DESC");
        
        // 需要自定义Mapper方法执行原生SQL
        // return baseMapper.selectByCustomSql(sql.toString());
        
        // 这里只是示例，实际不会这样实现
        return list();
    }

    // ==================== 纯Wrapper的核心优势 ====================
    
    /**
     * 优势1：类型安全
     * 编译时就能发现字段名错误
     */
    public List<User> typeSafetyExample() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        // ✅ 正确：编译时检查
        wrapper.eq("name", "张三");
        
        // ❌ 错误：如果字段名写错，IDE会提示（如果使用lambda表达式）
        // wrapper.eq(User::getName, "张三");  // 更安全的方式
        
        return list(wrapper);
    }
    
    /**
     * 优势2：自动参数绑定
     * 防止SQL注入，自动处理特殊字符
     */
    public List<User> parameterBindingExample(String userInput) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        // ✅ 安全：自动参数绑定，防止SQL注入
        wrapper.like("name", userInput);  // 即使userInput包含单引号等特殊字符也安全
        
        return list(wrapper);
    }
    
    /**
     * 优势3：数据库兼容性
     * 同一套代码在MySQL和PostgreSQL上都能正常运行
     */
    public List<User> databaseCompatibilityExample(Boolean isActive, LocalDateTime date) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        // ✅ 兼容：MyBatis-Plus自动处理数据库差异
        wrapper.eq("is_active", isActive)      // MySQL: 1/0, PostgreSQL: true/false
               .ge("created_at", date);           // 自动处理时间格式
        
        return list(wrapper);
    }
    
    /**
     * 优势4：代码复用
     * 条件构造逻辑可以复用
     */
    public QueryWrapper<User> buildCommonConditions(String keyword, Boolean isActive) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        if (keyword != null && !keyword.isEmpty()) {
            wrapper.and(w -> w
                .like("name", keyword)
                .or()
                .like("email", keyword)
            );
        }
        
        if (isActive != null) {
            wrapper.eq("is_active", isActive);
        }
        
        return wrapper;
    }
    
    // 复用条件构造逻辑
    public List<User> searchActiveUsers(String keyword) {
        QueryWrapper<User> wrapper = buildCommonConditions(keyword, true);
        wrapper.orderByDesc("created_at");
        return list(wrapper);
    }
    
    public long countActiveUsers(String keyword) {
        QueryWrapper<User> wrapper = buildCommonConditions(keyword, true);
        return count(wrapper);
    }
    
    /**
     * 优势5：链式调用的可读性
     * 代码逻辑清晰，易于理解
     */
    public List<User> readableChainExample() {
        return list(
            new QueryWrapper<User>()
                .like("name", "张")           // 姓名包含"张"
                .ge("age", 18)              // 年龄大于等于18
                .le("age", 65)              // 年龄小于等于65
                .eq("is_active", true)      // 状态为活跃
                .ge("balance", 1000.0)      // 余额大于等于1000
                .orderByDesc("balance")     // 按余额降序
                .orderByDesc("created_at")  // 再按创建时间降序
        );
    }
}

/*
 * 纯Wrapper方式 vs 传统方式对比总结：
 * 
 * 1. 代码安全性：
 *    - 纯Wrapper：类型安全，防SQL注入，参数自动绑定
 *    - 传统方式：字符串拼接，容易出错，需要手动防护
 * 
 * 2. 开发效率：
 *    - 纯Wrapper：IDE智能提示，链式调用，代码简洁
 *    - 传统方式：手写SQL，容易出错，调试困难
 * 
 * 3. 维护性：
 *    - 纯Wrapper：重构友好，条件复用，逻辑清晰
 *    - 传统方式：硬编码SQL，重构困难，逻辑分散
 * 
 * 4. 数据库兼容性：
 *    - 纯Wrapper：自动处理数据库差异，一套代码多数据库
 *    - 传统方式：需要为每个数据库写不同的SQL
 * 
 * 5. 性能：
 *    - 纯Wrapper：生成的SQL经过优化，性能相当
 *    - 传统方式：手写SQL可能更优化，但需要专业知识
 * 
 * 结论：
 * 纯Wrapper方式在大多数场景下都优于传统方式，
 * 只有在极复杂的查询或性能要求极高的场景下才考虑传统方式。
 */